import { BufferAttribute, BufferGeometry, Mesh, ShaderMaterial, Vector3} from "three";
import { CqkjMap } from "../Basic/CqkjMap";
import { MapElement, MapElementOption } from "../Basic/MapElement";
import { setValue } from "../Util/common";
import { PROJECTION } from "../Util/static";
import bg from "../Asset/inputbg.png";

export interface SpaceVerticalProfileOption extends MapElementOption {
  path:number[][];
  material: ShaderMaterial
}

const min=PROJECTION.altToZ(500)
const max=PROJECTION.altToZ(14000)

export class SpaceVerticalProfile extends MapElement<SpaceVerticalProfileOption>{
  mesh: Mesh<BufferGeometry, ShaderMaterial>;
  inputs: HTMLInputElement[];
  material: ShaderMaterial;
  anchor: Vector3;
  get show(): boolean {
    return this.option.show
  }
  set show(val: boolean) {
    setValue(this.option,'show',val,()=>{
      this.mesh.visible=val
    })
  }

  constructor(map: CqkjMap, option: SpaceVerticalProfileOption) {
    super(map, option)
    const path = option.path.map(e => [PROJECTION.lonToX(e[0]), PROJECTION.latToY(e[1])]);
    this.mesh = new Mesh(createGeometry(path),option.material)
    this.material=this.mesh.material
    map.scene.add(this.mesh)
    this.anchor = new Vector3(path[0][0], path[0][1], 0);
    this.inputs = [
      createInput(() => {
        const v = Number.parseFloat(this.inputs[0].value);
        if (!Number.isNaN(v)) {
          const value = Math.max(min, Math.min(max, PROJECTION.altToZ(v)));
          this.material.uniforms.u_hfilter.value[0] = value;
          const p = map.worldToPanel(new Vector3(0, 0, value).add(this.anchor));
          this.inputs[0].style.left = p.x + "px";
          this.inputs[0].style.top = p.y + "px";
        }
      }),
      createInput(() => {
        const v = Number.parseFloat(this.inputs[1].value);
        if (!Number.isNaN(v)) {
          const value = Math.max(min, Math.min(max, PROJECTION.altToZ(v)));
          this.material.uniforms.u_hfilter.value[1] = value;
          const p = map.worldToPanel(new Vector3(0, 0, value).add(this.anchor));
          this.inputs[1].style.left = p.x + "px";
          this.inputs[1].style.top = p.y + "px";
        }
      }),
    ];
    this.anchor = new Vector3(path[0][0], path[0][1], 0);
    map.show && this.onAfterViewChange();
  }

  onBeforeViewChange(): void {
    const container = this.map.renderer.domElement.parentElement;
    if (container) {
      this.inputs.forEach(e => {
        e.remove();
      });
    }
  }
  onAfterViewChange(): void {
    const { anchor, map } = this;
    const container = map.renderer.domElement.parentElement;

    if (container) {
      this.inputs.forEach((e, i) => {
        const h = this.material.uniforms.u_hfilter.value[i] as number;
        const p = map.worldToPanel(new Vector3(0, 0, h).add(anchor));
        e.style.left = p.x + "px";
        e.style.top = p.y + "px";
        e.value = PROJECTION.zToAlt(h).toFixed(0);
        container.appendChild(e);
      });
    }
  }
  onDestroy(): void {
    this.map.scene.remove(this.mesh);
    this.mesh.geometry.dispose();
    this.inputs.forEach(e=>e.remove())
  }

}



function createGeometry(points: number[][]) {
  const geometry = new BufferGeometry();
  const position = new Float32Array(points.length * 6);
  const index = new Uint16Array((points.length - 1) * 6);

  points.forEach((e, i) => {
    const i6 = i * 6;
    if (i) {
      const i2 = i * 2;
      index[i6 - 6] = i2 - 2;
      index[i6 - 5] = i2;
      index[i6 - 4] = i2 - 1;
      index[i6 - 3] = i2;
      index[i6 - 2] = i2 + 1;
      index[i6 - 1] = i2 - 1;
    }
    position[i6] = e[0];
    position[i6 + 1] = e[1];
    position[i6 + 2] = min;
    position[i6 + 3] = e[0];
    position[i6 + 4] = e[1];
    position[i6 + 5] = max;
  });

  geometry.attributes.position = new BufferAttribute(position, 3);
  geometry.index = new BufferAttribute(index, 1);

  return geometry;
}

function createInput(onChange: () => void) {
  const input = document.createElement("input");
  input.style.backgroundImage = `url(${bg})`;
  input.style.backgroundSize = "100% 100%";
  input.style.backgroundColor = "transparent";
  input.style.position = "absolute";
  input.style.zIndex = "10";
  input.style.width = "101px";
  input.style.height = "23px";
  input.style.top = "0";
  input.style.border = "none";
  input.style.outline = "none";
  input.style.color = "#CAFFEC";
  input.style.fontFamily = "Furore";
  input.style.fontSize = "13px";
  input.style.paddingLeft = "8px";
  input.style.paddingRight = "45px";
  input.style.boxSizing = "border-box";
  input.style.transform = "translate(-100%, -50%)";
  input.onblur = onChange;
  input.onkeydown = e => {
    if (e.code == "Enter") {
      onChange();
    }
  };
  return input;
}
